/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.annotation.ImportCandidates;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.support.SpringFactoriesLoader;

/**
 * 启用 Spring 应用上下文的自动配置，尝试根据你的类路径和已定义的 Bean 猜测并配置你可能需要的 Bean。
 * 自动配置类通常根据类路径中存在的内容以及你定义的 Bean 来应用。
 * 例如，如果你的类路径中存在 {@code tomcat-embedded.jar}，那么通常会希望配置一个
 * {@link TomcatServletWebServerFactory}（除非你自己定义了 {@link ServletWebServerFactory} Bean）。
 * <p>
 * 当使用 {@link SpringBootApplication @SpringBootApplication} 时，
 * 上下文的自动配置会自动启用，因此再添加此注解不会产生额外影响。
 * <p>
 * 自动配置会尽可能智能地进行配置，并在你自定义配置后自动退让。
 * 你可以使用 {@link #exclude()} 手动排除你不希望应用的配置（如果没有访问权限，可使用 {@link #excludeName()}）。
 * 你也可以通过属性 {@code spring.autoconfigure.exclude} 来排除。
 * 自动配置总是在用户定义的 Bean 注册之后应用。
 * <p>
 * 被 {@code @EnableAutoConfiguration} 注解的类（通常是通过 {@code @SpringBootApplication}）所在的包具有特殊意义，
 * 通常会被当作“默认包”。例如，在扫描 {@code @Entity} 类时会使用该包。
 * 一般推荐你将 {@code @EnableAutoConfiguration}（如果不使用 {@code @SpringBootApplication}）放在根包中，
 * 以便所有子包和类都能被扫描到。
 * <p>
 * 自动配置类是常规的 Spring {@link Configuration @Configuration} Bean。
 * 它们通过 {@link ImportCandidates} 和 {@link SpringFactoriesLoader} 机制定位（使用此类作为 key）。
 * 通常，自动配置 Bean 是 {@link Conditional @Conditional} Bean（大多数使用
 * {@link ConditionalOnClass @ConditionalOnClass} 和
 * {@link ConditionalOnMissingBean @ConditionalOnMissingBean} 注解）。
 *
 * @author Phillip Webb
 * @author Stephane Nicoll
 * @since 1.0.0
 * @see ConditionalOnBean
 * @see ConditionalOnMissingBean
 * @see ConditionalOnClass
 * @see AutoConfigureAfter
 * @see SpringBootApplication
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage    // 自动配置backPackage
@Import(AutoConfigurationImportSelector.class)  // 引入自动装配引导类
public @interface EnableAutoConfiguration {

	/**
	 * 可用于覆盖是否启用自动配置的环境属性。
	 */
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * 排除指定的自动配置类，使其永远不会被应用。
	 * @return 要排除的类
	 */
	Class<?>[] exclude() default {};

	/**
	 * 排除指定的自动配置类名，使其永远不会被应用。
	 * @return 要排除的类名
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}
